﻿/*----------------------------------------------------------------
           // Copyright (C) 2008 安华顺通(北京)科技有限公司
           // 版权所有。 
           //
           // 文件名：SysCompilerForm.cs
           // 文件功能描述：编译窗体，每个窗体生成一个DLL。
           //
           // 
           // 创建标识：周玉偈20081008
           //
           // 修改标识
           // 修改描述：
           //
           // 修改标识：
           // 修改描述：
//----------------------------------------------------------------*/

#region UsingStatements

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;             
using RuleCode.ObjectTree;
using Util = RuleCode.ObjectTree.Util;
using RuleCode.TemplateEngine;


#endregion

namespace RuleCode.compiler
{
    /// <summary>
    /// Compile Form.
    /// </summary>
    public class SysCompilerForm
    {

        private static SysCompilerForm sysCompilerForm;
        private static readonly string formPath =Util.GetFormsPath +"\\";// Util.OTPath + "\\Module\\Forms\\";
        private static readonly string fromPath = Util.OTPath + "\\Templates\\RuleCode.Forms.单表标准模块\\";
        private static readonly string toPathBase = Util.GetFormsPath + "\\";// Util.OTPath + "\\Module\\Forms\\";
        private static readonly string toWebFormPath = Util.GetOutputWebFormPath();
        
        private static readonly string fromWebFormPath = Util.OTPath + "\\templates\\WebForms\\";
        private static readonly string toWebDialogFormPath = Util.GetOutputWebDialogFormPath();
        private static readonly string fromWebDialogFormPath = fromWebFormPath + "Dialogs\\";

        private static readonly string keyFile = "D:\\snk\\RuleCode.Query.snk";
        private FormProperty formProperty;
        private readonly StringBuilder designerMember = new StringBuilder();
        private List<string> DeclarationList = new List<string>();
        private bool IsGrid = false;
        private bool IsEdtRelation = false;
        string formName;
        private FormStyle formStyle;

        public static SysCompilerForm Instance
        {
            get
            {
                if (sysCompilerForm == null)
                {
                    sysCompilerForm = new SysCompilerForm();
                }
                return sysCompilerForm;
            }
        }
        public void compileWebForm(SysTreeNode node)
        {
            formName = node.Text;
            node.ExpandAll();
            SysTreeNode dataSources = node.Nodes[1] as SysTreeNode;
            if (dataSources.Nodes.Count <= 0)
                return;
            SysTreeNode query = dataSources.Nodes[0] as SysTreeNode;
            if (query.Nodes.Count <= 0)
                return;
            SysTreeNode querydatasource = query.Nodes[1] as SysTreeNode;
            if (querydatasource.Nodes.Count <= 0)
                return;
            SysTreeNode table = querydatasource.Nodes[0] as SysTreeNode;
            string NameSpace = Util.RootWebFormNameSpace+".Forms";
            string TableName = table.Text;


            Template template1 = Template.FromString("tem", new StreamReader(fromWebFormPath + "Form.vm").ReadToEnd());
            TemplateManager template = new TemplateManager(template1);
            template.SetValue("NameSpace", NameSpace);

            template.SetValue("ClassName", TableName + "_Form");
            template.SetValue("TableName", TableName);
            template.SetValue("Fields", table.Nodes[0].Nodes);


            StreamWriter o = new StreamWriter(toWebFormPath + TableName + "_Form" + ".aspx", false);

            o.Write(template.Process());
            o.Close();

            template = TemplateManager.FromFile(fromWebFormPath + "Form.aspx.vm");
            template.SetValue("NameSpace", NameSpace);

            template.SetValue("ClassName", TableName + "_Form");
            template.SetValue("TableName", TableName);
            template.SetValue("Fields", table.Nodes[0].Nodes);
            o = new StreamWriter(toWebFormPath + TableName + "_Form" + ".aspx.cs", false);

            o.Write(template.Process());
            o.Close();


            template = TemplateManager.FromFile(fromWebFormPath + "Form.aspx.designer.vm");
            template.SetValue("NameSpace", NameSpace);

            template.SetValue("ClassName", TableName + "_Form");
            template.SetValue("TableName", TableName);
            template.SetValue("Fields", table.Nodes[0].Nodes);
            o = new StreamWriter(toWebFormPath + TableName + "_Form" + ".aspx.designer.cs", false);

            o.Write(template.Process());
            o.Close();

            template = TemplateManager.FromFile(fromWebDialogFormPath + "Update.aspx.designer.vm");
            template.SetValue("NameSpace", NameSpace);

            template.SetValue("ClassName", TableName + "_Update");
            template.SetValue("TableName", TableName);
            template.SetValue("Fields", table.Nodes[0].Nodes);
            o = new StreamWriter(toWebDialogFormPath + TableName + "_Update" + ".aspx.designer.cs", false);

            o.Write(template.Process());
            o.Close();

            template = TemplateManager.FromFile(fromWebDialogFormPath + "Update.aspx.vm");
            template.SetValue("NameSpace", NameSpace);

            template.SetValue("ClassName", TableName + "_Update");
            template.SetValue("TableName", TableName);
            template.SetValue("Fields", table.Nodes[0].Nodes);
            o = new StreamWriter(toWebDialogFormPath + TableName + "_Update" + ".aspx.cs", false);

            o.Write(template.Process());
            o.Close();

            template = TemplateManager.FromFile(fromWebDialogFormPath + "Update.vm");
            template.SetValue("NameSpace", NameSpace);

            template.SetValue("ClassName", TableName + "_Update");
            template.SetValue("TableName", TableName);
            template.SetValue("Fields", table.Nodes[0].Nodes);
            o = new StreamWriter(toWebDialogFormPath + TableName + "_Update" + ".aspx", false);

            o.Write(template.Process());
            o.Close();


            //将编译 好的文件添加到项目中
            if (Util_DTE.IsAddToProjectAtCompiled)
                Util_DTE.AddGeneratedFileToProject(node, GenerateFileType.WebForm ); 
        }



        public void compileForm(SysTreeNode node)
        {
            compileWebForm(node);
            return;
            //#region 初始化环境

            //string name = node.Text;
            //string op;
            //node.ExpandAll();
            //CodeCompileUnit CompileUnit = new CodeCompileUnit();

            //Util.SetProerptyInSilent(node);

            //CodeNamespace formNamespace = new CodeNamespace(SysDefalutNamespace.DefaultFormNamespace);
            //CompileUnit.Namespaces.Add(formNamespace);
            //CodeTypeDeclaration form = new CodeTypeDeclaration(name);
            ////设置类的继承。
            //form.IsClass = true;
            //form.TypeAttributes = TypeAttributes.Public;
            //form.IsPartial = true;
            ////todo:需要统一命名空间。
            //form.BaseTypes.Add("RuleCode.Query.Tables.Table");

            //// 将类型加入到容器的类型集合中
            //formNamespace.Types.Add(form);
            //formNamespace.Imports.Add(new CodeNamespaceImport("System"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("System.Text"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("System.ComponentModel"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("System.Data"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("RuleCode.Query.Type"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("RuleCode.ObjectTree"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("RuleCode.Query.Tables"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("RuleCode.Query.Enum"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("RuleCode.Query.AOTCommonClass"));
            //formNamespace.Imports.Add(new CodeNamespaceImport("System.Reflection"));

            //#endregion

            //#region  Build Constructor
            //string constructorString0 = "    public " + name + "() : base() { InitializeComponent(); }";
            //string constructorString1 = "    public " + name + "(string cmdText) : base(cmdText) { InitializeComponent(); }";
            //string constructorString2 = "    public " + name +
            //                            "(string cmdText, int count) : base(cmdText, count) { InitializeComponent(); }";

            //form.Members.Add(new CodeSnippetTypeMember(constructorString0));
            //form.Members.Add(new CodeSnippetTypeMember(constructorString1));
            //form.Members.Add(new CodeSnippetTypeMember(constructorString2));
            //#endregion

            //string disposeMember = "#region Dispose and Component";
            //disposeMember += "\r\r\n    private System.ComponentModel.IContainer components = null;" +
            //                 "\r\r\n    protected override void Dispose(bool disposing)" +
            //                 "\r\r\n       {" +
            //                 "\r\r\n           if (disposing && (components != null))" +
            //                 "\r\r\n           {" +
            //                 "\r\r\n               components.Dispose();" +
            //                 "\r\r\n           }" +
            //                 "\r\r\n       base.Dispose(disposing);" +
            //                 "\r\r\n       }";
            //disposeMember += "\r\n#endregion";
            //form.Members.Add(new CodeSnippetTypeMember(disposeMember));
            ////用StringBuilder适合大量的String拼接操作。

            //designerMember.Append("#region Designer generated code");
            //designerMember.Append("\r\n    private void InitializeComponent()");
            //designerMember.Append("\r\n    {");
            //addControl("", (SysTreeNode)node.LastNode);
            //designerMember.Append("\r\n    }");
            //designerMember.AppendLine();
            //designerMember.Append("\r\n");
            //foreach (var c in DeclarationList)
            //{

            //    designerMember.AppendLine("    " + c);
            //}
            //designerMember.AppendLine("#endregion");
            ////designerMember.AppendLine("    }//end of class");
            ////designerMember.AppendLine("}//end of namespace");
            //form.Members.Add(new CodeSnippetTypeMember(designerMember.ToString()));

            ////清除工作
            //designerMember.Remove(0, designerMember.Length);
            //DeclarationList.Clear();

            //#region 输出与编译

            ////下面是编译有关的内容

            //CodeGeneratorOptions options = new CodeGeneratorOptions();
            //options.BlankLinesBetweenMembers = false;
            //options.IndentString = "    ";
            //CompilerParameters cp = new CompilerParameters();


            //cp.OutputAssembly = Util.OTPath + "\\Module\\Forms\\" + name;
            //cp.ReferencedAssemblies.Add("System.dll");
            //cp.ReferencedAssemblies.Add("System.Data.dll");
            //cp.ReferencedAssemblies.Add("System.Xml.dll");
            //cp.ReferencedAssemblies.Add("mscorlib.dll");
            //cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            //cp.ReferencedAssemblies.Add("RuleCode.Query.Tables.dll");
            //cp.ReferencedAssemblies.Add("RuleCode.Query.Type.dll");
            //cp.ReferencedAssemblies.Add("RuleCode.Query.AOTCommonClass.dll");
            //cp.ReferencedAssemblies.Add("RuleCode.ObjectTree.dll");
            //cp.ReferencedAssemblies.Add("RuleCode.Query.Enum.dll");

            //cp.WarningLevel = 1;


            //cp.CompilerOptions = "/target:module /optimize /moduleassemblyname:RuleCode.ObjectTree.Form.dll";
            //cp.GenerateExecutable = false;
            //cp.GenerateInMemory = false;

            //TempFileCollection tfc = new TempFileCollection(Path.GetTempPath(), false);

            //CompilerResults cr = new CompilerResults(tfc);
            //CSharpCodeProvider csp = new CSharpCodeProvider();
            //DirectoryInfo dir = new DirectoryInfo(formPath);
            //if (!dir.Exists)
            //{
            //    dir.Create();
            //}
            //IndentedTextWriter tw =
            //    new IndentedTextWriter(new StreamWriter(formPath + node.Property.ID + ".Designer.cs", false), "    ");
            //csp.GenerateCodeFromCompileUnit(CompileUnit, tw, new CodeGeneratorOptions());

            //tw.Close();
            //#endregion
            Util.SetPropertyInSilent = true;
            Util.SetPropertyContent(node);
            Util.SetPropertyInSilent = false;


            formProperty = (FormProperty)node.Property;

            #region 复制文件夹

            string toPath;
            formName = node.Text;
            toPath = toPathBase;
            //复制文件夹
            //CopyDirectory(fromPath, toPath);
            ////遍历所有文件并替换字符串
            //scanDirectory(toPath, formName);
            using (StreamReader reader = new StreamReader(fromPath + "单表标准模块.cs", Encoding.UTF8))
            {
                string content = reader.ReadToEnd();
                content = replaceString(content, formName);
                using (StreamWriter writer = new StreamWriter(toPathBase + formName + FileExtendTypes.CSharp, false, Encoding.UTF8))
                {
                    writer.Write(content);
                }
            }
            using (StreamReader reader = new StreamReader(fromPath + "单表标准模块.designer.cs", Encoding.UTF8))
            {
                string content = reader.ReadToEnd();
                content = replaceString(content, formName);
                using (StreamWriter writer = new StreamWriter(toPathBase + formName + ".designer.cs", false, Encoding.UTF8))
                {
                    writer.Write(content);
                }
            }
            ReplaceString(fromWebFormPath, "单表模板.aspx", toWebFormPath, ".aspx");
            ReplaceString(fromWebFormPath, "单表模板.aspx.cs", toWebFormPath, ".aspx.cs");
            ReplaceString(fromWebFormPath, "单表模板_编辑.aspx", toWebFormPath, "_编辑.aspx");
            ReplaceString(fromWebFormPath, "单表模板_编辑.aspx.cs", toWebFormPath, "_编辑.aspx.cs");
            //CopyDirectory(toPath + "Query\\", xmlPath+ formName + "_Query\\");


            #endregion
        }

        private FormStyle FormStyle
        {
            get { return formStyle; }
        }

        private void ReplaceString(string fromPath, string orignaFileName, string toPathBase, string toFileExtendName)
        {
            using (StreamReader reader = new StreamReader(fromPath + orignaFileName, Encoding.UTF8))
            {
                string content = reader.ReadToEnd();
                content = content.Replace("单表模板", formName);
                using (StreamWriter writer = new StreamWriter(toPathBase + formName + toFileExtendName, false, Encoding.UTF8))
                {
                    writer.Write(content);
                }
            }

        }
        private void addControl(string parentName, SysTreeNode node)
        {
            foreach (SysTreeNode tempNode in node.Nodes)
            {


                //SysTreeNode tempNode = (SysTreeNode)c;
                Util.SetProerptyInSilent(tempNode);
                //todo:根据属性类型判断
                if (tempNode.Property is WinControlProperty)
                {
                    WinControlProperty winControlProperty = tempNode.Property as WinControlProperty;
                    string controlType = winControlProperty.ControlType;
                    string name = tempNode.Text;
                    designerMember.Append("\r\n        //");
                    designerMember.Append("\r\n        // " + name);
                    designerMember.Append("\r\n        //");
                    designerMember.Append("\r\n        this." + name + " = new " + controlType + "();");
                    DeclarationList.Add("private " + controlType + " " + name + ";");
                    foreach (var propertyInfo in winControlProperty.GetType().GetProperties())
                    {
                        if (propertyInfo.PropertyType == (typeof(string)) &&
                            propertyInfo.GetCustomAttributes(typeof(QuotableString), true).Length == 1)
                        {
                            designerMember.Append("\r\n        this." + name + "." + propertyInfo.Name + " = \"" +
                                                  propertyInfo.GetValue(winControlProperty, null) + "\";");
                            continue;
                        }
                        if (propertyInfo.PropertyType == (typeof(DateTime)))
                        {
                            designerMember.Append("\r\n        this." + name + "." + propertyInfo.Name + " = Convert.ToDateTime(\"" +
                                                  propertyInfo.GetValue(winControlProperty, null) + "\");");
                            continue;
                        }

                        //Default
                        {
                            designerMember.Append("\r\n        this." + name + "." + propertyInfo.Name + " = " +
                                                  propertyInfo.GetValue(winControlProperty, null) + ";");
                        }

                    }
                    if (parentName.Equals(string.Empty))
                    {
                        designerMember.Append("\r\n        this." + parentName + "Controls.Add(" + name + ");\r\n");
                    }
                    else
                    {
                        designerMember.Append("\r\n        this." + parentName + ".Controls.Add(" + name + ");\r\n");
                    }

                    addControl(name, tempNode);
                }
                if (tempNode.Property is GroupProperty)
                {
                    //todo:处理Group的情况
                    GroupProperty groupProperty = tempNode.Property as GroupProperty;
                    string tableName = groupProperty.DataSource;
                    string tableGroup = groupProperty.DataGroup;
                    SysTreeNode parentNode = tempNode.Parent as SysTreeNode;
                    WinControlProperty property = parentNode.Property as WinControlProperty;
                    string type = property.ControlType;
                    if (type.Equals("RuleDataGridView"))
                    {
                        IsGrid = true;
                    }
                    DictClass dictClass = new DictClass();
                    SysTreeNode table = dictClass.Tables.Nodes.Find(tableName, false)[0] as SysTreeNode;
                    SysTreeNode fields = table.Nodes.Find(OT.Fields, false)[0] as SysTreeNode;
                    SysTreeNode groups = table.Nodes.Find(OT.FieldGroups, false)[0] as SysTreeNode;
                    SysTreeNode group = groups.Nodes.Find(tableGroup, false)[0] as SysTreeNode;
                    foreach (SysTreeNode groupField in group.Nodes)
                    {
                        Util.SetProerptyInSilent(groupField);
                        GroupFieldProperty groupFieldProperty = groupField.Property as GroupFieldProperty;
                        SysTreeNode field = fields.Nodes.Find(groupFieldProperty.DataField, false)[0] as SysTreeNode;
                        Util.SetProerptyInSilent(field);
                        SysTreeNode edt =
                            dictClass.EDTs.Nodes.Find((field.Property as TableFieldProperty).ExtendedDataType, false)[0]
                            as SysTreeNode;
                        //扩展类型是否有关系
                        if (edt.LastNode.Nodes.Count != 0)
                        {
                            IsEdtRelation = true;
                        }
                        //
                        Util.SetProerptyInSilent(edt);
                        string edtType = (edt.Property as EDTProperty).EDTType;
                        edtType = edtType.Substring(1, edtType.Length - 1);
                        string typeName;
                        if (IsGrid)
                        {
                            if (IsEdtRelation)
                            {
                                typeName = "RuleRelationDataGridColumn";
                                IsEdtRelation = false;
                            }
                            else
                            {
                                typeName = "Rule" + edtType + "DataGridColumn";
                            }
                            IsGrid = false;
                        }
                        else
                        {
                            if (IsEdtRelation)
                            {
                                typeName = "RuleRelationField";
                                IsEdtRelation = false;
                            }
                            else
                            {
                                typeName = "Rule" + edtType + "Field";
                            }
                        }
                        //得到了类型名，初始化类型
                        string name = field.Text;
                        designerMember.Append("\r\n        //");
                        designerMember.Append("\r\n        // " + name);
                        designerMember.Append("\r\n        //");
                        designerMember.Append("\r\n        this." + name + " = new " + typeName + "();");
                        DeclarationList.Add("private " + typeName + " " + name + ";");
                        //加入属性

                        if (IsGrid)
                        {

                        }
                        designerMember.AppendLine();
                    }
                    Console.WriteLine(tempNode.Text + parentName);
                }

            }

        }

        public void compileForms(SysTreeNode nodes)
        {
            foreach (SysTreeNode node in nodes.Nodes)
            {
                compileForm(node);
            }
        }


        //遍历文件夹
        private void scanDirectory(string _Directory, string _formName)
        {
            DirectoryInfo DirectoryArray = new DirectoryInfo(_Directory);
            //获取该文件夹下的文件列表
            FileInfo[] Files = DirectoryArray.GetFiles();
            //获取该文件夹下的文件夹列表
            DirectoryInfo[] Directorys = DirectoryArray.GetDirectories();
            //遍历所有文件
            foreach (FileInfo inf in Files)
            {
                //替换字符串操作
                dealDirectory(_Directory + "\\" + inf.Name, _formName);
            }
            //逐个获取文件夹名称，并递归调用方法本身
            foreach (DirectoryInfo Dir in Directorys)
            {
                scanDirectory(_Directory + "\\" + Dir.Name, _formName);
            }
        }

        //处理要替换的文本文件
        private void dealDirectory(string _Path, string _formName)
        {
            string str = "";
            StreamReader streamReader = new StreamReader(_Path, Encoding.UTF8);

            while (streamReader.Peek() >= 0)
            {
                str += replaceString(streamReader.ReadLine(), _formName) + "\r\r\n";
            }
            streamReader.Close();
            File.Delete(_Path); //删除原来文件
            StreamWriter streamWriter = new StreamWriter(replaceString(_Path, _formName), false, Encoding.UTF8);
            streamWriter.Write(str);
            streamWriter.Close();
        }

        //替换字符串
        private string replaceString(string _sourceString, string _formName)
        {
            string ret;
            ret = _sourceString;
            ret = ret.Replace("单表标准模块", _formName);
            ret = ret.Replace("@SYS21952", formProperty.Label);
            ret = ret.Replace("@SYS13342", formProperty.Label);
            return ret;
        }

        //获取文件夹名，截取“\”
        private int DirectoryName(string DirectoryPath)
        {
            int j = 0;
            char[] c = DirectoryPath.ToCharArray();
            for (int i = c.Length - 1; i >= 0; i--) //从后面截取
            {
                j = i;
                if (c[i] == '\\')
                {
                    break; //遇"\"调处,并返回"\"的位置
                }
            }
            return j + 1;
        }

        //复制文件夹，
        private void CopyDirectory(string fromDirectory, string toDirectory)
        {
            #region//递归

            //string s = fromDirectory.Substring(DirectoryName(fromDirectory)); //获取文件夹名
            //if (Directory.Exists(toDirectory + "\\" + s))
            //{
            //    Directory.Delete(toDirectory + "\\" + s, true); //若文件夹存在，不管目录是否为空，删除
            //    Directory.CreateDirectory(toDirectory + "\\" + s); //删除后，重新创建文件夹
            //}
            //else
            //{
            //    Directory.CreateDirectory(toDirectory + "\\" + s); //文件夹不存在，创建
            //}
            //DirectoryInfo DirectoryArray = new DirectoryInfo(fromDirectory);
            //FileInfo[] Files = DirectoryArray.GetFiles(); //获取该文件夹下的文件列表
            ////DirectoryInfo[] Directorys = DirectoryArray.GetDirectories(); //获取该文件夹下的文件夹列表
            //foreach (FileInfo inf in Files) //逐个复制文件
            //{
            //    File.Copy(fromDirectory + inf.Name, toDirectory + );
            //}
            //foreach (DirectoryInfo Dir in Directorys) //逐个获取文件夹名称，并递归调用方法本身
            //{
            //    CopyDirectory(fromDirectory + "\\" + Dir.Name, toDirectory + "\\" + s);
            //}

            #endregion
        }
    }
}